package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SpringLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.TitledBorder;

import com.pagosoft.plaf.PlafOptions;

public class Gui {

	public void createGui(String programName) {
		JFrame 		mainFrame = new JFrame(programName);
		Container 	mainContent = mainFrame.getContentPane();
		
		/* Borders. */
		TitledBorder title;
		PlafOptions.setAsLookAndFeel();
		
		/* The progress bar. */
		JProgressBar progressBar = new JProgressBar();
		
		
		
		/**
		 * References to component objects needed to set up
		 * GUI behaviour.
		 */
		
		/* Menus */
		JMenuBar 	mainMenu = new JMenuBar();
		JMenu 		file = new JMenu("File");
		JMenuItem 	file_exit = new JMenuItem();
		
			/* Set up menu content and show it. */
			file.add(file_exit);
			mainMenu.add(file);
			mainFrame.setJMenuBar(mainMenu);
		
		/* Fields where user can input dumping/insertion data. */
		JTextField textStart = 		new JTextField();
		JTextField textStop = 		new JTextField();
		JTextField pointerStart = 	new JTextField();
		JTextField pointerStop = 	new JTextField();
		JTextField header = 		new JTextField();
		JTextField x000 = 			new JTextField();
		
		JComboBox pointerType = getPointerTypes();
			
			/* 
			 * Set the width of one field, causing all other in the 
			 * same component panel to comply.
			 */
			textStart.setColumns(10);
			
			/* Labels for each field. */
			JLabel textStartLabel = 		new JLabel("Text start: 0x", JLabel.TRAILING);
			JLabel textStopLabel = 			new JLabel("Text stop: 0x", JLabel.TRAILING);
			JLabel pointerStartLabel = 		new JLabel("Pointer start: 0x", JLabel.TRAILING);
			JLabel pointerStopLabel = 		new JLabel("Pointer stop: 0x", JLabel.TRAILING);
			JLabel headerLabel = 			new JLabel("Header (+/-): 0x", JLabel.TRAILING);
			JLabel x000Label = 				new JLabel("x000 offset: 0x", JLabel.TRAILING);
			JLabel pointerTypeLabel = 		new JLabel("Pointer type: ", JLabel.TRAILING);
			
			/* Text field list to initialize Spring layout. */
			JLabel[] 		settingLabels = new JLabel[] {textStartLabel, textStopLabel, pointerStartLabel, pointerStopLabel, headerLabel, x000Label, pointerTypeLabel};
			JComponent[] 	settingFields = new JComponent[] {textStart, textStop, pointerStart, pointerStop, header, x000, pointerType};
		
		/* File selection fields. */
		JTextField selectedGameFile = 		new JTextField();
		JTextField selectedTableFile = 		new JTextField();
		JComboBox readFormat = 				getReadFormats();
			
			/* 
			 * Set the width of one field, causing all other in the 
			 * same component panel to comply.
			 */
			selectedGameFile.setColumns(20);
		
			/* File labels. */
			JLabel selectedGameLabel = 		new JLabel("Game file", JLabel.LEFT);
			JLabel selectedTableLabel = 	new JLabel("Table file", JLabel.LEFT);
			JLabel readFormatLabel =		new JLabel("Text format", JLabel.LEFT);
			
			/* Browse buttons. */
			JButton gameBrowse = 	new JButton("Browse");
			JButton pointerBrowse = new JButton("Browse");
			JButton tableBrowse = 	new JButton("Browse");
			
			/* Spring layout list. */
			JLabel[] fileLabels = 		new JLabel[] {selectedGameLabel, selectedTableLabel, readFormatLabel};
			JComponent[] fileFields = 	new JComponent[] {selectedGameFile, selectedTableFile, readFormat};
			JButton[] fileButtons = 	new JButton[] {gameBrowse, tableBrowse};
		
		
		/* Advanced settings fields. */
		JTextField selectedPointerFile = 	new JTextField();
		JTextField fixedLength =			new JTextField();
		JTextField fixedPad =				new JTextField();
		
			/* 
			 * Set the width of one field, causing all other in the 
			 * same component panel to comply.
			 */
			//selectedPointerFile.setColumns(10);
		
			/* Advanced settings labels. */
			JLabel selectedPointerLabel = 	new JLabel("Pointer file:", JLabel.LEFT);
			JLabel fixedLengthLabel = 		new JLabel("Fixed length:", JLabel.LEFT);
			JLabel fixedPadLabel = 			new JLabel("Padding byte:", JLabel.LEFT);
			
			/* Field and label collections. */
			JLabel[] advancedLabels = 			new JLabel[] {selectedPointerLabel, fixedLengthLabel, fixedPadLabel};
			JComponent[] advancedFields = 		new JComponent[] {selectedPointerFile, fixedLength, fixedPad};
			JButton[] advancedButtons = 		new JButton[] {pointerBrowse};
			
		/* Dump / Insert buttons */
		JButton dumpButton = 	new JButton("Dump");
		JButton insertButton = 	new JButton("Insert");
			
		/**
		 * Layout components.
		 */
		
		/* Tabs that contain all content. */
		JTabbedPane tabs = new JTabbedPane();

		/* 
		 * Main layout that contains everything in the dump/insert tab. 
		 * 
		 * The layout stores all content in .CENTER, using a gridbag layout.
		 * The layout itself is stored in a flowlayout to keep it
		 * left aligned inside the tab.
		 * 
		 * A progress bar is also stored in .SOUTH.
		 */
		JPanel dumpInsertPanel = 	new JPanel(new BorderLayout()); // Settings center, xml east, progressbar south.
		JPanel dumpInsertLeftAlign = new JPanel(new FlowLayout(FlowLayout.LEFT));
			   dumpInsertLeftAlign.add(dumpInsertPanel);
		
		/* Add progress bar to .SOUTH. */
		dumpInsertPanel.add(progressBar, BorderLayout.SOUTH);
		progressBar.setValue(25);
				
			/*
			 * Grid layout contained in the dumpInsert panel.
			 * Stored in .WEST.
			 * 
			 * ------------------
			 * |Settings | Files|
			 * ------------------
			 * |Advanced | Log  |
			 * ------------------
			 */
			JPanel 				dumpGrid = 			new JPanel();
			GridBagLayout 		dumpGridLayout = 	new GridBagLayout();
			GridBagConstraints 	dumpGridCon = 		dumpGridLayout.getConstraints(dumpGrid);
			dumpGrid.setLayout(dumpGridLayout);
			
			dumpGridCon.fill = GridBagConstraints.HORIZONTAL; // Make all grid components expand horizontally if needed
			dumpGridCon.anchor = GridBagConstraints.NORTHWEST; // Make all grid components position themselves in the upper left corner of the cell and grow downwards
	
				/* 
				 * Container that contains the setting elements that the 
				 * vertical layout should display.
				 */
				JPanel springSettingsContainer = setupSettingsGrid(settingLabels, settingFields);
				
				/* Set border. */
				title = BorderFactory.createTitledBorder("Settings");
				springSettingsContainer.setBorder(title);
				
					/* Add settings spring panel to a vertical layout. */
					JPanel verticalSettingsAlign = new JPanel(new VerticalLayout());
					verticalSettingsAlign.add(springSettingsContainer);					
		
						/* Add settings to insert/dump panel. */
						dumpGridCon.gridx = 0;
						dumpGridCon.gridy = 0;
						dumpGridCon.gridheight = 2;
						dumpGrid.add(verticalSettingsAlign);
						dumpGridLayout.setConstraints(verticalSettingsAlign, dumpGridCon);
					
					/* Add buttons to a horizontal layout. */
					JPanel horizontalAlign = new JPanel(new FlowLayout(FlowLayout.LEFT));
					horizontalAlign.add(dumpButton);
					horizontalAlign.add(insertButton);

							/* Add horizontal layout (buttons) to vertical layout. */
							verticalSettingsAlign.add(horizontalAlign);	
				
				/*
				 * Container that contains the file settings for
				 * dumping / inserting.			
				 */
				JPanel springFileContainer = setupFilesGrid(fileLabels, fileFields, fileButtons);
				
				/* Set border. */
				springFileContainer.setBorder(BorderFactory.createTitledBorder("Files"));
				
					/* Add settings spring panel to a vertical layout. */
					JPanel verticalFilesAlign = new JPanel(new VerticalLayout());
					verticalFilesAlign.add(springFileContainer);
					
						/* Add settings to insert/dump panel. */
						dumpGridCon.gridx = 1;
						dumpGridCon.gridy = 0;
						dumpGridCon.gridheight = 1;
						dumpGrid.add(verticalFilesAlign);
						dumpGridLayout.setConstraints(verticalFilesAlign, dumpGridCon); // How the panel behaves in the grid.
				
				
				/*
				* Container that contains the advanced settings
				* for dumping / inserting.			
				*/
				JPanel springAdvancedContainer = setupAdvancedGrid(advancedLabels, advancedFields, advancedButtons);
				
				/* Set border. */
				springAdvancedContainer.setBorder(BorderFactory.createTitledBorder("Advanced"));
				
				dumpGridCon.gridx = 1;
				dumpGridCon.gridy = 1;
				dumpGrid.add(springAdvancedContainer);
				dumpGridLayout.setConstraints(springAdvancedContainer, dumpGridCon);
				
				/* Add the grid to a left aligned panel. */
				dumpInsertPanel.add(dumpGrid);
				
				/* Add insert settings panel to tabs. */
				tabs.addTab("Dump / Insert", dumpInsertLeftAlign);
				tabs.addTab("Preview", new JPanel());
			
				
			/* Add tree to grid. */
			dumpGridCon.gridx = 2;
			dumpGridCon.gridy = 0;
			dumpGridCon.gridheight = 2;
			JTree tree = new JTree();
			dumpGrid.add(tree);
			dumpGridLayout.setConstraints(tree, dumpGridCon);
				
		/* Add tabs to mainframe. */
		mainContent.add(tabs);	
		
		/**
		 * Misc settings.
		 */
		/* Set window exit behaviour. */
		mainFrame.addWindowListener(new MyWindowListener());
		
		mainFrame.pack();
		mainFrame.setVisible(true);
	}
	

	
	/**
	 * Sets up a container that includes the settings labels
	 * and textfields in a spring layout.
	 */
	private JPanel setupSettingsGrid(JLabel[] labels, JComponent[] text) {
		JPanel panel = new JPanel(new SpringLayout());
		int length = Math.min(labels.length, text.length);
		
		for (int i = 0; i < length; i++) {
			panel.add(labels[i]);
			panel.add(text[i]);
		}
		
		/* Make a grid out of it. */
		SpringUtilities.makeCompactGrid(panel, length, 2, 0, 0, 5, 5);
		
		return panel;
	}
	
	/**
	 * Sets up a container that includes the settings labels
	 * and textfields in a spring layout.
	 */
	private JPanel setupFilesGrid(JLabel[] labels, JComponent[] text, JButton[] buttons) {
		JPanel panel = new JPanel(new SpringLayout());
		int length = Math.min(labels.length, text.length);
		JButton invisibleButton;
		
		for (int i = 0; i < length; i++) {
			panel.add(labels[i]);
			panel.add(text[i]);
			
			invisibleButton = new JButton();
			invisibleButton.setVisible(false);
			
			if (i < buttons.length) {
				panel.add(buttons[i]);
			} else {
				panel.add(invisibleButton);
			}
			
		}
		
		/* Make a grid out of it. */
		SpringUtilities.makeCompactGrid(panel, length, 3, 0, 0, 5, 5);
		
		return panel;
	}
	
	/**
	 * Sets up a container that includes the settings labels
	 * and textfields in a spring layout.
	 */
	private JPanel setupAdvancedGrid(JLabel[] labels, JComponent[] text, JButton[] buttons) {
		JPanel panel = new JPanel(new SpringLayout());
		int length = Math.min(labels.length, text.length);
		JButton invisibleButton;
		
		
		for (int i = 0; i < length; i++) {
			panel.add(labels[i]);
			panel.add(text[i]);
			
			invisibleButton = new JButton();
			invisibleButton.setVisible(false);
			
			if (i < buttons.length) {
				panel.add(buttons[i]);
			} else {
				panel.add(invisibleButton);
			}
			
		}
		
		/* Make a grid out of it. */
		SpringUtilities.makeCompactGrid(panel, length, 3, 0, 0, 5, 5);
		
		return panel;
	}
	
	/**
	 * Returns a combo box with all possible
	 * pointer types.
	 */
	private JComboBox getPointerTypes() {
		String[] options = new String[] {"Snes", "Nes"};
		JComboBox box = new JComboBox(options);
		
		return box;
	}
	
	/**
	 * Returns a combo box with all possible
	 * script/tablefile read formats.
	 */
	private JComboBox getReadFormats() {
		String[] options = new String[] {"ISO-8859-1", "US-ASCII", "UTF-8", "UTF-16"};
		JComboBox box = new JComboBox(options);
		
		return box;
	}
	
	/**
	 * Handles gui exit action.
	 */
	private class MyWindowListener implements WindowListener {
		public void windowClosing(WindowEvent arg0) {
		    System.exit(0);
		  }

		  public void windowOpened(WindowEvent arg0) {
		  }

		  public void windowClosed(WindowEvent arg0) {
		  }

		  public void windowIconified(WindowEvent arg0) {
		  }

		  public void windowDeiconified(WindowEvent arg0) {
		  }

		  public void windowActivated(WindowEvent arg0) {
		  }

		  public void windowDeactivated(WindowEvent arg0) {
		  }
	}
	
}


